using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Text;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using Terra.Core.Security.Models;
using Terra.Core.Security.Options;

namespace Terra.Core.Security.Services;

/// <summary>
/// JWT服务实现
/// </summary>
public class JwtService : IJwtService
{
    private readonly JwtOptions _jwtOptions;
    private readonly SigningCredentials _signingCredentials;
    private readonly TokenValidationParameters _tokenValidationParameters;

    public JwtService(IOptions<JwtOptions> jwtOptions)
    {
        _jwtOptions = jwtOptions.Value;

        // 验证密钥长度
        var keyBytes = Encoding.UTF8.GetBytes(_jwtOptions.SecretKey);
        if (keyBytes.Length * 8 < 256)
        {
            throw new ArgumentException("JWT密钥长度必须至少为256位（32字节）");
        }

        var key = new SymmetricSecurityKey(keyBytes);
        _signingCredentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

        _tokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = _jwtOptions.Issuer,
            ValidAudience = _jwtOptions.Audience,
            IssuerSigningKey = key,
            ClockSkew = TimeSpan.Zero
        };
    }

    /// <summary>
    /// 生成访问令牌
    /// </summary>
    public string GenerateAccessToken(UserIdentity userIdentity)
    {
        var now = DateTime.UtcNow;
        var claims = new List<Claim>
        {
            new(JwtRegisteredClaimNames.Sub, userIdentity.UserId),
            new(JwtRegisteredClaimNames.UniqueName, userIdentity.Username),
            new(JwtRegisteredClaimNames.Email, userIdentity.Email),
            new(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
            new(JwtRegisteredClaimNames.Iat, new DateTimeOffset(now).ToUnixTimeSeconds().ToString())
        };

        // 添加角色声明
        claims.AddRange(userIdentity.Roles.Select(role => new Claim(ClaimTypes.Role, role)));

        // 添加权限声明
        claims.AddRange(userIdentity.Permissions.Select(permission => new Claim("permission", permission)));

        // 添加自定义声明
        claims.AddRange(userIdentity.Claims.Select(claim => new Claim(claim.Key, claim.Value)));

        var token = new JwtSecurityToken(
            issuer: _jwtOptions.Issuer,
            audience: _jwtOptions.Audience,
            claims: claims,
            notBefore: now,
            expires: now.AddMinutes(_jwtOptions.ExpirationMinutes),
            signingCredentials: _signingCredentials
        );

        return new JwtSecurityTokenHandler().WriteToken(token);
    }

    /// <summary>
    /// 生成刷新令牌
    /// </summary>
    public string GenerateRefreshToken()
    {
        var randomBytes = new byte[32];
        using var rng = RandomNumberGenerator.Create();
        rng.GetBytes(randomBytes);
        return Convert.ToBase64String(randomBytes);
    }

    /// <summary>
    /// 验证访问令牌
    /// </summary>
    public bool ValidateAccessToken(string token)
    {
        try
        {
            var tokenHandler = new JwtSecurityTokenHandler();
            var principal = tokenHandler.ValidateToken(token, _tokenValidationParameters, out var validatedToken);

            // 添加更多验证逻辑
            var jwtToken = validatedToken as JwtSecurityToken;
            if (jwtToken == null || !jwtToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256))
            {
                return false;
            }

            // 验证令牌是否过期
            var expires = jwtToken.ValidTo;
            if (expires < DateTime.UtcNow)
            {
                return false;
            }

            return true;
        }
        catch (Exception)
        {
            return false;
        }
    }

    /// <summary>
    /// 从令牌中获取用户身份信息
    /// </summary>
    public UserIdentity GetUserIdentityFromToken(string token)
    {
        try
        {
            var tokenHandler = new JwtSecurityTokenHandler();
            var principal = tokenHandler.ValidateToken(token, _tokenValidationParameters, out var validatedToken);

            var userIdentity = new UserIdentity
            {
                UserId = principal.FindFirst(JwtRegisteredClaimNames.Sub)?.Value ?? string.Empty,
                Username = principal.FindFirst(JwtRegisteredClaimNames.UniqueName)?.Value ?? string.Empty,
                Email = principal.FindFirst(JwtRegisteredClaimNames.Email)?.Value ?? string.Empty,
                Roles = principal.FindAll(ClaimTypes.Role).Select(c => c.Value).ToList(),
                Permissions = principal.FindAll("permission").Select(c => c.Value).ToList()
            };

            // 获取自定义声明
            var customClaims = principal.Claims
                .Where(c => !IsSystemClaim(c.Type))
                .ToDictionary(c => c.Type, c => c.Value);

            userIdentity.Claims = customClaims;
            return userIdentity;
        }
        catch (Exception ex)
        {
            // 添加异常信息记录
            Console.WriteLine($"Token validation failed: {ex.Message}");
            return null;
        }
    }

    private static bool IsSystemClaim(string claimType)
    {
        return claimType.StartsWith("http://") ||
               claimType.StartsWith("https://") ||
               claimType == ClaimTypes.Role ||
               claimType == "permission" ||
               claimType == JwtRegisteredClaimNames.Sub ||
               claimType == JwtRegisteredClaimNames.UniqueName ||
               claimType == JwtRegisteredClaimNames.Email ||
               claimType == JwtRegisteredClaimNames.Jti ||
               claimType == JwtRegisteredClaimNames.Iat;
    }
}